package controller

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
	"uap/pkg/app"

	"github.com/gin-gonic/gin"
	"github.com/shirou/gopsutil/disk"
	"github.com/shirou/gopsutil/mem"
	"github.com/shirou/gopsutil/v3/cpu"
)

type Monitor struct {
	Cpuinfo  *CPUInfo    `json:"cpuInfo"`
	Meminfo  *MemInfo    `json:"memInfo"`
	Diskinfo *[]DiskInfo `json:"diskInfo"`
}

func NewMoniror() *Monitor {
	return &Monitor{}
}

type CPUInfo struct {
	UsedPercent float64 `json:"usedPercent"`
	Cores       int     `json:"cores"`
}

type MemInfo struct {
	Total       uint64  `json:"total"`
	Used        uint64  `json:"used"`
	UsedPercent float64 `json:"usedPercent"`
}

type DiskInfo struct {
	DiskPart    string  `json:"diskPart"`
	Total       uint64  `json:"total"`
	UsedPercent float64 `json:"usedPercent"`
}

func (a *Monitor) Query(c *gin.Context) {
	cpuInfo := GetCpuInfo()
	memInfo := GetMemInfo()
	diskInfo := GetDiskInfo()
	monitor := Monitor{Cpuinfo: cpuInfo, Meminfo: memInfo, Diskinfo: diskInfo}
	app.Success(c, monitor)
}

func GetMemInfo() *MemInfo {
	mm, err := mem.VirtualMemory()
	if err != nil {
		fmt.Println("get memory info fail. err： ", err)
	}
	// 获取总内存大小，单位GB
	memTotal := mm.Total / 1024 / 1024 / 1024
	// 获取已用内存大小，单位MB
	memUsed := mm.Used / 1024 / 1024 / 1024
	// 可用内存大小
	// memAva := mm.Available / 1024 / 1024
	// 内存可用率
	memUsedPercent := mm.UsedPercent
	memInfo := MemInfo{Total: memTotal, Used: memUsed, UsedPercent: Decimal(memUsedPercent)}
	return &memInfo
}

func GetDiskInfo() *[]DiskInfo {
	diskPart, err := disk.Partitions(false)
	if err != nil {
		fmt.Println(err)
	}
	disks := []DiskInfo{}
	for _, dp := range diskPart {
		diskInfo := DiskInfo{}
		diskInfo.DiskPart = dp.Mountpoint
		diskUsed, _ := disk.Usage(dp.Mountpoint)
		diskInfo.Total = diskUsed.Total / 1024 / 1024 / 1024
		diskInfo.UsedPercent = Decimal(diskUsed.UsedPercent)
		disks = append(disks, diskInfo)
	}
	return &disks
}

func GetCpuInfo() *CPUInfo {
	cpuPercent, _ := cpu.Percent(time.Second, true)
	cpuNumber, _ := cpu.Counts(true)
	cpuInfo := CPUInfo{Cores: cpuNumber, UsedPercent: Decimal(cpuPercent[0])}
	return &cpuInfo
}

func GetLocalIP() (ip string, err error) {
	conn, err := net.Dial("udp", "8.8.8.8:53")
	if err != nil {
		fmt.Println(err)
		return
	}
	localAddr := conn.LocalAddr().(*net.UDPAddr)
	ip = strings.Split(localAddr.String(), ":")[0]
	return
}

func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}
